package com.apobates.forum.core.impl.dao;

import com.apobates.forum.core.dao.BoardModeratorDao;
import com.apobates.forum.core.entity.BoardModerator;
import com.apobates.forum.core.entity.BoardModeratorRoleHistory;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 *
 * @author xiaofanku
 * @since 20200514
 */
@Repository
public class BoardModeratorDaoImpl implements BoardModeratorDao{
    @PersistenceContext
    private EntityManager entityManager;
    private final static Logger logger = LoggerFactory.getLogger(BoardModeratorDaoImpl.class);
    
    @Override
    public Stream<BoardModerator> findAllByBoardId(long boardId) {
        return entityManager.createQuery("SELECT bm FROM BoardModerator bm WHERE bm.boardId = ?1", BoardModerator.class).setParameter(1, boardId).getResultStream();
    }
    
    @Override
    public List<BoardModerator> findUsedByBoardId(long boardId) {
        return entityManager.createQuery("SELECT bm FROM BoardModerator bm WHERE bm.boardId = ?1 AND bm.status = ?2", BoardModerator.class).setParameter(1, boardId).setParameter(2, true).getResultList();
    }
    
    @Override
    public Stream<BoardModerator> findAllUsedByBoardGroup(int boardGroupId) {
        if(0>=boardGroupId){
            return Stream.empty();
        }
        return entityManager.createQuery("SELECT bm FROM BoardModerator bm WHERE bm.boardId = ?1 AND bm.volumesId = ?2 AND bm.volumesMaster = ?3 AND bm.status = ?4", BoardModerator.class)
                .setParameter(1, 0)
                .setParameter(2, boardGroupId)
                .setParameter(3, true)
                .setParameter(4, true)
                .getResultStream();
    }
    
    @Override
    public Optional<BoardModerator> findOneByBoardAndMember(long boardId, long memberId) {
        try {
            BoardModerator bm = entityManager.createQuery("SELECT bm FROM BoardModerator bm WHERE bm.boardId = ?1 AND bm.memberId = ?2 AND bm.volumesMaster = ?3", BoardModerator.class)
                    .setParameter(1, boardId)
                    .setParameter(2, memberId)
                    .setParameter(3, false)
                    .getSingleResult();
            return Optional.ofNullable(bm);
        } catch (javax.persistence.NoResultException e) {
            return Optional.empty();
        }
    }
    
    @Override
    public Optional<BoardModerator> findOneByBoardGroupAndMember(int boardGroupId, long memberId) {
        try {
            BoardModerator bm = entityManager.createQuery("SELECT bm FROM BoardModerator bm WHERE bm.boardId = ?1 AND bm.memberId = ?2 AND bm.volumesId = ?3 AND bm.volumesMaster = ?4", BoardModerator.class)
                    .setParameter(1, 0)
                    .setParameter(2, memberId)
                    .setParameter(3, boardGroupId)
                    .setParameter(4, true)
                    .getSingleResult();
            return Optional.ofNullable(bm);
        } catch (javax.persistence.NoResultException e) {
            return Optional.empty();
        }
    }
    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public Optional<Boolean> remove(long id) {
        int affect = 0;
        try {
            affect = entityManager.createQuery("DELETE FROM BoardModerator bm WHERE bm.id = ?1").setParameter(1, id).executeUpdate();
        } catch (Exception e) {
            Optional.empty();
        }
        if (affect == 1) {
            entityManager.createQuery("DELETE FROM BoardModeratorActionIndex bma WHERE bma.moderatorId = ?1").setParameter(1, id).executeUpdate();
        }
        return affect == 1 ? Optional.of(true) : Optional.empty();
    }
    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void save(BoardModerator entity) {
        entityManager.persist(entity);
    }
    
    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public Optional<BoardModerator> pushModerator(BoardModerator moderator, BoardModeratorRoleHistory memberRoleHistory) {
        entityManager.persist(moderator);
        entityManager.flush();
        if (moderator.getId() > 0) {
            memberRoleHistory.setModeratorId(moderator.getId());
            entityManager.persist(memberRoleHistory);
            return Optional.of(moderator);
        }
        return Optional.empty();
    }
    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void deleteModerator(BoardModeratorRoleHistory history) {
        Objects.requireNonNull(history);
        int affect = 0;
        try {
            affect = entityManager.createQuery("DELETE FROM BoardModerator bm WHERE bm.id = ?1").setParameter(1, history.getModeratorId()).executeUpdate();
        } catch (Exception e) {
            Optional.empty();
        }
        if (affect == 1) {
            entityManager.createQuery("DELETE FROM BoardModeratorActionIndex bma WHERE bma.moderatorId = ?1").setParameter(1, history.getModeratorId()).executeUpdate();
            affect = entityManager.createQuery("UPDATE BoardModeratorRoleHistory bmr SET bmr.status = ?1 WHERE bmr.id = ?2 AND bmr.status = ?3")
                .setParameter(1, false)
                .setParameter(2, history.getId())
                .setParameter(3, true)
                .executeUpdate();
        }
    }
    
    @Override
    public Optional<BoardModerator> findOne(Long primaryKey) {
        BoardModerator bm = entityManager.find(BoardModerator.class, primaryKey);
        return Optional.ofNullable(bm);
    }
    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public Optional<Boolean> edit(BoardModerator updateEntity) {
        try {
            entityManager.merge(updateEntity);
            return Optional.of(true);
        } catch (Exception e) {
            return Optional.empty();//.failure(e);
        }
    }
    
    @Override
    public Stream<BoardModerator> findAll() {
        return entityManager.createQuery("SELECT bm FROM BoardModerator bm", BoardModerator.class).getResultStream();
    }
    
    @Override
    public long count() {
        return -1L;
    }
}